/*******************************************************************************
 * 共享内存模拟测试程序
 * 功能：
 * 1. 创建共享内存并初始化测试数据
 * 2. 定期更新：new_val替换old_val，然后生成新的new_val
 * 3. 支持优雅退出和资源清理
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/select.h>
#include "shmem.h"

// ==================== 配置参数 ====================
#define SHM_NAME        "shm_test"          // 共享内存名称
#define SHM_SIZE        4096                // 共享内存大小
#define NUM_NODES       14                  // 模拟节点数量
#define UPDATE_INTERVAL 1000000             // 更新间隔(微秒)

// ==================== 数据结构 ====================
typedef union {
    int b_val;   // 布尔型
    int i_val;   // 整型
    float f_val; // 浮点型
} val_t;

typedef struct {
    int key;       // 节点唯一标识
    int type;      // 数据类型 (0:bool, 1:int, 2:float)
    int dev_type;  // 设备类型
    val_t old_val; // 旧值
    val_t new_val; // 新值
    int ret;       // 状态码
} std_node;

// ==================== 全局变量 ====================
volatile sig_atomic_t running = 1;      // 程序运行标志
struct shm_param shm_para;              // 共享内存参数
std_node *nodes = NULL;                 // 共享内存节点指针

// ==================== 函数声明 ====================
void handle_signal(int sig);
void init_shared_memory();
void init_test_data();
void update_node_values();
void print_node_values();

// ==================== 主函数 ====================
int main(int argc, char* argv[]) {
    srand(time(NULL));
    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
    
    printf("启动共享内存模拟测试程序...\n");
    init_shared_memory();
    init_test_data();
    
    printf("模拟数据初始化完成，开始循环更新...\n");
    printf("按Ctrl+C或Q退出...\n");
    
    while (running) {
        update_node_values();
        print_node_values();
        
        // 非阻塞检查用户输入
        fd_set fds;
        struct timeval tv = {0, 100000}; // 100ms
        FD_ZERO(&fds);
        FD_SET(STDIN_FILENO, &fds);
        
        if (select(STDIN_FILENO+1, &fds, NULL, NULL, &tv) > 0) {
            if (getchar() == 'Q' || getchar() == 'q') running = 0;
        }
        
        usleep(UPDATE_INTERVAL);
    }
    
    printf("\n正在清理资源...\n");
    shm_del(&shm_para);
    printf("模拟测试程序已安全停止\n");
    return 0;
}

// ==================== 功能函数实现 ====================

void handle_signal(int sig) {
    printf("接收到信号 %d, 准备退出...\n", sig);
    running = 0;
}

void init_shared_memory() {
    if (shm_init(&shm_para, SHM_NAME, SHM_SIZE) < 0) {
        fprintf(stderr, "共享内存初始化失败\n");
        exit(EXIT_FAILURE);
    }
    
    int *p_num = (int *)shm_getaddr(&shm_para);
    if (p_num == NULL) {
        fprintf(stderr, "共享内存映射失败\n");
        shm_del(&shm_para);
        exit(EXIT_FAILURE);
    }
    
    *p_num = NUM_NODES;
    nodes = (std_node *)(p_num + 1);
}

void init_test_data() {
    for (int i = 0; i < NUM_NODES; i++) {
        nodes[i].key = i + 1;
        nodes[i].type = rand() % 3;
        nodes[i].dev_type = rand() % 10;
        nodes[i].ret = 0;
        
        // 初始化old_val和new_val为相同值
        switch (nodes[i].type) {
            case 0: 
                nodes[i].old_val.b_val = nodes[i].new_val.b_val = rand() % 2;
                break;
            case 1: 
                nodes[i].old_val.i_val = nodes[i].new_val.i_val = rand() % 100;
                break;
            case 2: 
                nodes[i].old_val.f_val = nodes[i].new_val.f_val = (float)(rand() % 10000) / 100.0f;
                break;
        }
    }
}

// 修改后的关键函数：new_val替换old_val，然后生成新的new_val
void update_node_values() {
    for (int i = 0; i < NUM_NODES; i++) {
        // 将当前new_val复制到old_val
        switch (nodes[i].type) {
            case 0: 
                nodes[i].old_val.b_val = nodes[i].new_val.b_val;
                nodes[i].new_val.b_val = rand() % 2;
                break;
            case 1: 
                nodes[i].old_val.i_val = nodes[i].new_val.i_val;
                nodes[i].new_val.i_val = rand() % 100;
                break;
            case 2: 
                nodes[i].old_val.f_val = nodes[i].new_val.f_val;
                nodes[i].new_val.f_val = (float)(rand() % 10000) / 100.0f;
                break;
        }
    }
}

void print_node_values() {
    printf("\n当前节点值:\n");
    printf("Key\tType\tOld Value\tNew Value\n");
    printf("---\t----\t---------\t---------\n");
    
    for (int i = 0; i < NUM_NODES; i++) {
        printf("%d\t", nodes[i].key);
        switch (nodes[i].type) {
            case 0: printf("bool\t"); break;
            case 1: printf("int\t"); break;
            case 2: printf("float\t"); break;
        }
        
        // 打印old_val
        switch (nodes[i].type) {
            case 0: printf("%d\t\t", nodes[i].old_val.b_val); break;
            case 1: printf("%d\t\t", nodes[i].old_val.i_val); break;
            case 2: printf("%.2f\t\t", nodes[i].old_val.f_val); break;
        }
        
        // 打印new_val
        switch (nodes[i].type) {
            case 0: printf("%d\n", nodes[i].new_val.b_val); break;
            case 1: printf("%d\n", nodes[i].new_val.i_val); break;
            case 2: printf("%.2f\n", nodes[i].new_val.f_val); break;
        }
    }
}